package tako.wisers.com.android;

import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;
import javax.servlet.ServletException;
import javax.servlet.http.*;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import tako.wisers.com.android.jdo.Geohash;
import tako.wisers.com.android.jdo.PMF;
import tako.wisers.com.android.jdo.StationJdo;

@SuppressWarnings("serial")
public class TakoServiceServlet extends HttpServlet {
	private static final String LAT = "Lat";
	private static final String LONG = "Long";
	private static final String TYPE = "type";
	private static final String SUBTYPE = "subtype";
	private static final String SHOP = "shop";
	private static final String LOCATION = "location";
	private final PersistenceManagerFactory pmf = PMF.get();
	private final static String SQL = "SELECT FROM tako.wisers.com.android.jdo.StationJdo WHERE cellCode == '%s' && type == %s && subType == %s && shop == %s && location == %s";
	private final static int RETURN_SIZE = 20;

	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		try {
			doPut(req, resp);
		} catch (ServletException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doPut(req, resp);
	}

	@Override
	public void doPut(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		PersistenceManager pm = pmf.getPersistenceManager();
		String latStr = req.getParameter(LAT);
		String lonStr = req.getParameter(LONG);
		String type = req.getParameter(TYPE);
		String subtye = req.getParameter(SUBTYPE);
		String shop = req.getParameter(SHOP);
		String location = req.getParameter(LOCATION);
		JSONObject result = new JSONObject();
		try {
			if (latStr == null || lonStr == null || type == null) {
				result.put("result", "failed");
			}
			List<StationJdo> jdos = getJdos(pm, latStr, lonStr, type, subtye,
					shop, location);
			String content = makeJson(jdos, result);
			OutputStream os = resp.getOutputStream();
			os.write(content.getBytes("UTF-8"));
			os.flush();
			os.close();
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			pm.close();
		}
	}

	private String makeJson(List<StationJdo> jdos, JSONObject result)
			throws JSONException {
		JSONArray jdoArray = new JSONArray();
		for (StationJdo jdo : jdos) {
			JSONObject obj = new JSONObject();
			obj.put("station_name", jdo.getName().getValue());
			obj.put("address", jdo.getAddress().getValue());
			obj.put("city", jdo.getCity().getValue());
			obj.put("country_code", jdo.getCountyCode().getValue());
			obj.put("phone", jdo.getPhone().getValue());
			obj.put("station_type", jdo.getType());
			obj.put("station_subType", jdo.getSubType());
			obj.put("lat", jdo.getLat());
			obj.put("lon", jdo.getLon());
			obj.put("url", jdo.getUrl().getValue());
			String photoUrl = jdo.getPhotoURL() == null ? "" : jdo
					.getPhotoURL().getValue();
			obj.put("photo_url", photoUrl);
			obj.put("other_info", jdo.getInfo().getValue());
			jdoArray.put(obj);
		}
		result.put("content", jdoArray);
		result.put("result", "succes");
		return result.toString();
	}

	@SuppressWarnings("unchecked")
	private List<StationJdo> getJdos(PersistenceManager pm, String latStr,
			String lonStr, String... pramas) {
		if (pramas.length != 4)
			return null;
		Geohash geohash = new Geohash();
		double lat = new Double(latStr);
		double lon = new Double(lonStr);
		List<StationJdo> jdos = new ArrayList<StationJdo>();
		List<String> cellCodeList = new ArrayList<String>();
		for (int i = 0; i < 11; i++) {
			double latFix = fixLacation(i >> 2, lat);
			double lonFix = fixLacation(i & 3, lon);
			if (latFix == -1 || lonFix == -1)
				continue;
			String cellCode = geohash.encode(latFix, lonFix);
			if (cellCodeList.contains(cellCode)) {
				continue;
			} else {
				cellCodeList.add(cellCode);
			}
			String sql = String.format(SQL, cellCode, pramas[0], pramas[1],
					pramas[2], pramas[3]);
			if (pramas[1].equals("0")) {
				sql = sql.substring(0, sql.lastIndexOf("&&"));
			}
			Query query = pm.newQuery(sql);
			query.setRange(0, RETURN_SIZE - jdos.size());
			Iterator<StationJdo> itr = ((List) query.execute()).iterator();
			while (itr.hasNext()) {
				StationJdo jdo = itr.next();
				if (jdo == null)
					continue;
				jdos.add(jdo);
			}
			if (jdos.size() >= 20)
				break;
		}

		return jdos;
	}

	private double fixLacation(int type, double loc) {
		if (type == 0)
			return loc;
		else if (type == 1)
			return loc - Geohash.GRIDE_CELL;
		else if (type == 2)
			return loc + Geohash.GRIDE_CELL;
		else
			return -1;
	}

	public static void main(String[] args) {
		TakoServiceServlet tss = new TakoServiceServlet();
		// tss.getJdos(null, "22.280296", "114.183333", "3");
	}
}
